package net.lainiao.dicom.common.storage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.HashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class StorageCloudBatchUtils implements StorageBatchUtils {

    private static Logger logger = LoggerFactory.getLogger(StorageCloudBatchUtils.class);
    private String type;
    private String endPoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;
    private Integer threadCount = 5;

    public StorageCloudBatchUtils(String type, String endPoint, String accessKeyId, String accessKeySecret, String bucketName) {
        this.type = type;
        this.endPoint = endPoint;
        this.accessKeyId = accessKeyId;
        this.accessKeySecret = accessKeySecret;
        this.bucketName = bucketName;
    }


    @Override
    public boolean getObjects(HashMap<String, String> hashMap) {
        LinkedBlockingQueue<String> linkedBlockingQueue = new LinkedBlockingQueue<>();
        for (String val : hashMap.keySet()) {
            linkedBlockingQueue.add(val);
        }
        AtomicInteger errorCount = new AtomicInteger(0);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(threadCount, threadCount, 5, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
        for (int i = 0; i < threadCount; i++) {
            executor.submit(new Runnable() {
                @Override
                public void run() {
                    StorageCloudUtil storageCloudUtil = new StorageCloudUtil(type, endPoint, accessKeyId, accessKeySecret, bucketName);
                    try {
                        storageCloudUtil.open();
                        String objectName = null;
                        while ((objectName = linkedBlockingQueue.poll()) != null) {
                            if (errorCount.get() > 0) {
                                break;
                            }
                            File targetFile = new File(hashMap.get(objectName));
                            int count=0;
                            while (count<3){
                                try {
                                    storageCloudUtil.getObject(objectName, targetFile);
                                    logger.debug("DownLoaded File:" + targetFile.getAbsolutePath());
                                    break;
                                }
                                catch (Exception e) {
                                    logger.error("Download File Error ObjectName:"+objectName+" targetFile:"+targetFile.getAbsolutePath()+" Message:"+e.toString());
                                    count++;
                                }
                            }
                            if(count>=3){
                                throw new Exception("Download File Error ObjectName:"+objectName);
                            }

                        }
                    }
                    catch (Exception e) {
                        errorCount.incrementAndGet();
                        logger.error("Download Files Error:" + e.toString());
                    }
                    finally {
                        storageCloudUtil.close();
                    }
                }
            });
        }
        executor.shutdown();
        try {
            while (!executor.awaitTermination(2, TimeUnit.SECONDS)) ;
        }
        catch (InterruptedException e) {

        }
        executor = null;
        if (errorCount.get() > 0) {
            return false;
        }
        return true;
    }


    @Override
    public boolean putObjects(HashMap<String, File> hashMap) {
        LinkedBlockingQueue<String> linkedBlockingQueue = new LinkedBlockingQueue<>();
        for (String val : hashMap.keySet()) {
            linkedBlockingQueue.add(val);
        }
        AtomicInteger errorCount = new AtomicInteger(0);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(threadCount, threadCount, 5, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
        for (int i = 0; i < threadCount; i++) {
            executor.submit(new Runnable() {
                @Override
                public void run() {
                    StorageCloudUtil storageCloudUtil = new StorageCloudUtil(type, endPoint, accessKeyId, accessKeySecret, bucketName);
                    try {
                        storageCloudUtil.open();
                        String objectName = null;
                        while ((objectName = linkedBlockingQueue.poll()) != null) {
                            if (errorCount.get() > 0) {
                                break;
                            }

                            File targetFile = hashMap.get(objectName);
                            int count=0;
                            while (count<3){
                                try {
                                    storageCloudUtil.putObject(objectName, targetFile);
                                    logger.debug("Uploaded File:" + targetFile.getAbsolutePath());
                                    break;
                                }
                                catch (Exception e) {
                                    logger.error("Upload File Error ObjectName:"+objectName+"File:" + targetFile.getAbsolutePath()+" Message:"+e.toString());
                                    count++;
                                }
                            }

                            if(count>=3){
                                throw new Exception("Upload File Error ObjectName:"+objectName+" File:"+targetFile.getAbsolutePath());
                            }
                        }
                    }
                    catch (Exception e) {
                        errorCount.incrementAndGet();
                        logger.error("Upload Files Error:" + e.toString());
                    }
                    finally {
                        storageCloudUtil.close();
                    }
                }
            });
        }
        executor.shutdown();
        try {
            while (!executor.awaitTermination(2, TimeUnit.SECONDS)) ;
        }
        catch (InterruptedException e) {

        }

        if (errorCount.get() > 0) {
            return false;
        }
        return true;
    }
}
